#include "CanvasHandler.h"
#include "Sington.h"
#include "tcpmanager.h"
#include <QtConcurrent>


CanvasHandler::CanvasHandler(QObject *parent) :
    QObject(parent),
    m_cursorShape(Qt::ArrowCursor)
{
    registerFunctor();
}

CanvasHandler *CanvasHandler::instance()
{
    return Sington<CanvasHandler>::getInstance();
}

void CanvasHandler::canvasClear()
{
    stk.clear();
    qDebug() << "clear" << " " << stk.size();
    emit clearCanvas();
}

Qt::CursorShape CanvasHandler::cursorShape() const
{
    return m_cursorShape;
}

ToolType CanvasHandler::currentToolType() const
{
    return m_currentToolType;
}

void CanvasHandler::sendFigure(const ToolType type, const int x, const int y, const int w, const int h)
{
    qDebug() << "Preparing sendFigure.";
    // 使用后台线程
    QtConcurrent::run([=](){
        // protobuf解析
        using namespace PROTO;

        SerializeManager *serializeManager = SerializeManager::instance();
        Shape shape;
        if (type == ToolType::Circle)
        {
            shape = serializeManager->getACircle(x, y, h, w);
            pushFigure(shape); // 当前图像压入栈
        }
        else if (type == ToolType::Rectangle)
        {
            shape = serializeManager->getARect(x, y, h, w);
            pushFigure(shape); // 当前图像压入栈
        }
        else if (type == ToolType::Backout)
        {
            qDebug() << "backout";
            shape = serializeManager->getABackout();
        }
        else if (type == ToolType::Clear)
        {
            qDebug() << "clear";
            shape = serializeManager->getAClear();
        }
        else
        {
            return ;
        }

        QByteArray data = QByteArray::fromStdString(shape.SerializeAsString());

        // 发送
        TcpManager* tcpManager = TcpManager::instance();
        auto sockets = tcpManager->getSockets();
        for (auto it = sockets.begin(); it != sockets.end(); ++it)
        {
            qDebug() << "Send a Figure to" << (*it)->socketName() << "figure type is" << type;
            (*it)->sendFigure(data);
        }
    });
}

void CanvasHandler::recover()
{
    qDebug() << "recover==============";

    QtConcurrent::run([]() {
        CanvasHandler::instance()->recoverCanvas();
    });

}

void CanvasHandler::canvasBackout()
{
    qDebug() << "===========backout " << stk.size();
    if (stk.empty())
        return;
    stk.pop_back();
    recoverCanvas();
}

void CanvasHandler::saveToFile(QString path)
{
    bool ret = SerializeManager::instance()->saveToFile(stk, path);
    if (!ret)
    {
        emit notice("文件保存失败");
        return;
    }
    qDebug() << "=================saveToFile" << stk.size();
}

void CanvasHandler::loadFromFile(QString path)
{
    canvasClear();
    bool ret = SerializeManager::instance()->parseFromFile(stk, path);
    if (!ret)
    {
        emit notice("文件解析失败");
        return;
    }
    qDebug() << "===========laod " << stk.size();
    recover();
}

void CanvasHandler::pushFigure(Shape& sp)
{
    QMutexLocker lock(&m_mutex);
    stk.push_back(sp);

    qDebug() << stk.size();
}

void CanvasHandler::setCursorShape(const Qt::CursorShape cursorShape)
{
    if (m_cursorShape != cursorShape) {
        m_cursorShape = cursorShape;
        emit cursorShapeChanged();
    }
}

void CanvasHandler::setCurrentToolType(const ToolType &type)
{
    if (type != m_currentToolType) {
        m_currentToolType = type;
        emit currentToolTypeChanged();
    }
}

void CanvasHandler::registerFunctor()
{
    using namespace std::placeholders;
    TcpManager* manager = TcpManager::instance();
    qDebug() << "Try to register functor";
    manager->registerFunctor(TransferType::CANVAS_TYPE, std::bind(&CanvasHandler::handleNewBlock, this, _1, _2));
}

void CanvasHandler::handleNewBlock(qint64 magicNumber, QByteArray data)
{
    using namespace PROTO;
    Shape shape;
    qDebug() << "receive";
    shape.ParseFromString(data.toStdString());
    if (shape.type() == Shape_ShapeType_RECT) {
        qDebug() << "收到一个矩形" << magicNumber;
        pushFigure(shape);
        emit draw("Rect", shape.x(), shape.y(), shape.h(), shape.w());
    } else if (shape.type() == Shape_ShapeType_CIRCLE) {
        qDebug() << "收到一个圆形" << magicNumber;
        pushFigure(shape);
        emit draw("Circle", shape.x(), shape.y(), shape.h(), shape.w());
    } else if (shape.type() == Shape_ShapeType_BACKOUT) {
        canvasBackout();
    } else if (shape.type() == Shape_ShapeType_CLEAR) {
        canvasClear();
    }

}

void CanvasHandler::recoverCanvas()
{
    emit clearCanvas();
    for (auto sp : stk)
    {
        if (sp.type() == Shape_ShapeType_RECT)
        {
            setCurrentToolType(ToolType::Rectangle);
            emit draw("Rect", sp.x(), sp.y(), sp.h(), sp.w());
        }
        else if (sp.type() == Shape_ShapeType_CIRCLE)
        {
            setCurrentToolType(ToolType::Circle);
            emit draw("Circle", sp.x(), sp.y(), sp.h(), sp.w());
        }
    }
}
